
<!doctype html>
<html>
<head>
	<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
	<script src="http://code.jquery.com/jquery-latest.js"></script>
	<title>jQuery.width</title>
	<style type="text/css">
		div{
			width: 3000px;
			height: 100px;
		}
	</style>
</head>
<body>

<div style="background:red;border:20px solid #ccc;">获取元素大小</div>

<button id="test1">display:none状态下,无法获取</button>
<button id="test2">模拟jQuery的.width()方法，在隐藏的时候也能获取</button>

<ul></ul>

<script type="text/javascript">

var div = document.querySelectorAll('div')[0]

$('#test1').click(function(){
	div.style.display = "none";
	show('隐藏状态下div.style.width: '+ div.style.width)
	show('隐藏状态下div.offsetWidth: '+ div.offsetWidth)
})


//获取样式合集
function getStyles(elem) {
	return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
};

//交换样式
function swap(elem, options, callback, args) {
	var ret, name,
		old = {};
	for (name in options) {
		old[name] = elem.style[name];
		elem.style[name] = options[name];
	}
	ret = callback.apply(elem, args || []);
	for (name in options) {
		elem.style[name] = old[name];
	}
	return ret;
};

//获取当前样式
function curCSS(elem,name) {
	var computed = getStyles(elem);
	var ret = computed.getPropertyValue(name) || computed[name];
	return ret;
}

//获取宽高
function getWidthOrHeight(elem, name, extra){
	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
	//需要extra判断是否是content/border的处理
	//代码太长,这里省略了,具体可以可以参考jQuery的源码
	return val;
}

var cssShow = {
	display: "block",
	position: "absolute",
	visibility: "hidden"
}


$('#test2').click(function(){
	var elem = div;
	function width() {
		if( /^(none|table(?!-c[ea]).+)/.test(curCSS(div, 'display'))  ){
			return swap(elem, cssShow, function() {
				return getWidthOrHeight(elem, 'width', 'content');
			})
		}
	}
	show('模拟jQuery.width的处理: '+ width())
})

function show(data){
	$('ul').append('<li>'+ data +'</li>')
}

</script>
</body>
</html>